/*
 * This file is part of LangMan.
 *
 * LangMan is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 2 of the License, or
 * (at your option) any later version.
 *
 * LangMan is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with LangMan.  If not, see <http://www.gnu.org/licenses/>.
 */

package langman.business.io;

import langman.business.config.Config;
import langman.business.config.ConfigService;
import langman.business.config.LanguageDescription;
import langman.business.config.SetDescription;
import langman.business.data.TranslationException;
import langman.business.data.model.Category;
import langman.business.data.model.Language;
import langman.business.data.model.LanguageSet;
import langman.business.profiles.Profile;
import langman.util.doping.Inject;
import langman.util.doping.SingletonBean;
import org.apache.logging.log4j.LogManager;

import java.io.File;
import java.util.*;

@SingletonBean
public class LanguageLoaderService {
    private final List<LanguageSet> sets = new ArrayList<>();
    private final ConfigService configService;
    private Language referenceLanguage;
    private List<Language> languages = new ArrayList<>();
    private Map<String, Category> categoryMap = new LinkedHashMap<>();
    private Profile profile;

    @Inject
    public LanguageLoaderService(ConfigService configService) {
        this.configService = configService;
    }

    public List<LanguageSet> getSets() {
        return Collections.unmodifiableList(sets);
    }

    public void readConfig(Profile profile) throws TranslationException {
        this.profile = profile;

        Config config = configService.loadConfig(profile.getConfigFile());

        List<SetDescription> setDescriptions = config.getSetDescriptions();
        for (SetDescription setDescription : setDescriptions) {
            int numberOfLanguages = setDescription.getLanguageDescriptions().size();
            loadSet(numberOfLanguages, setDescription);
        }

        if (referenceLanguage == null) {
            throw new TranslationException("No reference language defined in configuration!");
        }
    }

    private void loadSet(int numberOfLanguages, SetDescription setDescription) throws TranslationException {
        languages = new ArrayList<>();
        categoryMap = new LinkedHashMap<>();

        for (LanguageDescription languageDescription : setDescription.getLanguageDescriptions()) {
            loadLanguage(numberOfLanguages, languageDescription);
        }

        sets.add(new LanguageSet(setDescription.getName(), languages, new ArrayList<>(categoryMap.values())));

    }

    private void loadLanguage(int numberOfLanguages, LanguageDescription languageDescription) {
        String languageName = languageDescription.getName();
        String languageFileName = languageDescription.getFileName();
        File languageFile = new File(profile.getRootFolder(), languageFileName);

        try {
            DataLoader loader = new DataLoader(numberOfLanguages, languageName, languageFile, categoryMap, referenceLanguage);
            loader.load();

            Language language = loader.getLanguage();
            boolean isReference = languageDescription.isReference();
            language.setReference(isReference);

            if (isReference) {
                referenceLanguage = language;
            }
            languages.add(language);
        } catch (TranslationException e) {
            LogManager.getLogger(getClass()).error("Error while loading language " + languageDescription.getName() + " from file " + languageFile, e);
        }


    }
}
